跳到主要内容

Redis 缓存雪崩等问题

缓存雪崩问题

缓存雪崩是指缓存在某一时刻出现大规模的 key 失效,导致大量请求直接打到数据库上,造成数据库压力过大甚至宕机的现象。

造成原因:

  1. Redis宕机
  2. 大量key采用了相同的过期时间

解决方案流程图:

解决方案说明:

  1. 事前预防

    • 设置随机过期时间,避免集中失效
    • 实现多级缓存架构
    • 热点数据永不过期(逻辑过期)
    • 保证 Redis 高可用(主从+哨兵/集群)
  2. 事中处理

    • 互斥锁控制数据库访问
    • 熔断降级机制
  3. 事后恢复

    • 开启 Redis 持久化快速恢复

缓存击穿问题

缓存击穿是指某个热点 key 失效时,大量并发请求同时访问这个 key,导致请求都打到数据库的现象。

  • 缓存雪崩:大规模 key 同时失效
  • 缓存击穿:单个热点 key 失效

解决方案流程图:

Go实现示例

func GetHotData(key string) (string, error) {
// 1. 先查缓存
data, err := rdb.Get(ctx, key).Result()
if err == nil {
return data, nil
}

// 2. 缓存未命中,尝试获取互斥锁
lockKey := "lock:" + key
locked, err := rdb.SetNX(ctx, lockKey, 1, 10*time.Second).Result()
if err != nil {
return "", err
}

if locked {
// 3. 获取锁成功,查询数据库
defer rdb.Del(ctx, lockKey)

dbData := queryFromDB(key)
rdb.Set(ctx, key, dbData, time.Hour)
return dbData, nil
} else {
// 4. 获取锁失败,短暂等待后重试
time.Sleep(50 * time.Millisecond)
return GetHotData(key)
}
}

缓存穿透问题

缓存穿透是指查询一个不存在的数据,缓存和数据库都没有,但每次请求都会打到数据库。

布隆过滤器解决方案流程图:

布隆过滤器原理图:

布隆过滤器特点

  • 判断不存在:100%准确
  • 判断存在:可能有误判(false positive)
  • 空间效率高,时间复杂度O(k)

方案二:缓存空值(最常用/生产里常见)

当数据库返回不存在时,将空结果或占位值写入缓存,并设置一个较短的过期时间(如 30s 或 1min),避免频繁访问数据库。

  • 优点:实现简单、维护成本低。
  • 缺点:可能导致缓存大量无效的 key(需要设置较短 TTL)。

缓存预热和降级

系统上线时如何避免缓存冷启动问题?在缓存服务不可用时如何保证系统稳定性?

这种时候可以使用缓存预热和降级策略

策略流程图:

缓存降级流程图:

降级策略层级

  1. 一般:网络抖动等偶发问题,自动降级
  2. 警告:成功率波动(95%-100%),自动/人工降级
  3. 错误可用率 < 90%,根据情况降级
  4. 严重:数据错误,紧急人工降级